<?php
// +--------------------------------------------------------------------------------------------------------------------
// | 本文件是《FastChat》的一部分，所有代码、文字、图片、样式、风格等版权归作者所有，如有复制、仿冒、抄袭、盗用，FastAdmin和作者将追究法律责任
// +--------------------------------------------------------------------------------------------------------------------
// | @作者: 妙码生花 <1094963513@qq.com>
// +--------------------------------------------------------------------------------------------------------------------
// | @唯一授权链接: https://www.fastadmin.net/store/fastchat.html
// +--------------------------------------------------------------------------------------------------------------------

namespace addons\fastchat\controller;

use think\Db;
use think\Hook;
use fast\Random;
use think\Cookie;
use think\Config;
use app\admin\library\Auth;
use think\addons\Controller;
use addons\fastchat\library\Common;

class Index extends Controller
{

    protected $noNeedLogin = ['initialize', 'load_message_prompt', 'upload'];

    protected $chat_config;

    protected $token_info = false;

    protected $token_list = [];// 要发送给前台的token（前台利用这些token链接websocket）

    public function _initialize()
    {
        // 跨域检测
        check_cors_request();
        parent::_initialize();

        $this->chat_config          = get_addon_config('fastchat');
        $upload['upload']           = \app\common\model\Config::upload();
        $upload['upload']['cdnurl'] = $upload['upload']['cdnurl'] ?: cdnurl('', true);
        $view_cdn                   = config('view_replace_str.__CDN__');
        $view_cdn                   = $view_cdn ?: cdnurl('', true);
        $this->chat_config          = array_merge($this->chat_config, $upload, ['__CDN__' => $view_cdn]);

        // 配置排除
        $except_config = [
            'worker_process_number',
            'register_port',
            'gateway_process_number',
            'internal_start_port'
        ];
        foreach ($except_config as $value) {
            if (in_array($value, $except_config)) {
                unset($this->chat_config[$value]);
            }
        }

        // 用户登录
        $modulename                                  = $this->request->request('modulename');
        $tourists_token                              = $this->request->request('tourists_token');
        $this->token_list['fastchat_tourists_token'] = $tourists_token ?: Cookie::get('fastchat_user');

        if (!$modulename) {
            $this->result(null, 0, $this->chat_config['chat_name'] . ' 模块未知', 'json');
        }

        if ($modulename == 'admin') {
            // 验证管理员身份
            $auth = Auth::instance();
            if ($auth->isLogin()) {
                $this->token_info = Common::check_admin(false, $auth->id);

                if ($this->token_info) {
                    // workerman 中不支持 PHP session和cookie，所以 $auth 类失效
                    // 此处对管理员 token 加密稍作修改，供客服自动登录使用
                    $keeptime   = 864000;
                    $expiretime = time() + $keeptime;

                    // 原规则为单纯的id，若需修改附加的字符串，请将`Common::check_admin`方法里边的附加字符串一起修改
                    $sign = $this->token_info['admin_id'] . 'fastchat_admin_sign_additional';

                    $key                                = md5(md5($sign) . md5($keeptime) . md5($expiretime) . $this->token_info['token']);
                    $cookie_data                        = [$this->token_info['admin_id'], $keeptime, $expiretime, $key];
                    $this->token_list['fastchat_token'] = implode('|', $cookie_data);
                    unset($this->token_info['token']);
                }
            }
        } elseif ($modulename != 'admin') {
            // 验证用户身份
            $auth  = \app\common\library\Auth::instance();
            $token = Cookie::get('token');

            if ($token) {
                $auth->init($token);
                if ($auth->isLogin()) {
                    $this->token_info = Common::check_fa_user(null, $auth->id);
                    $cookie_httponly  = config('cookie.httponly');

                    // workerman 中不支持 PHP session和cookie，所以 $auth 类失效
                    // 在开启 $cookie_httponly 时，对用户的 token 加密稍作修改，供客服自动登录使用
                    if ($this->token_info) {

                        if (!$cookie_httponly) {
                            $this->token_list['fastchat_token'] = $token;
                        } else {

                            // 若需修改附加的字符串，请将`Common::check_fa_user`方法里边的附加字符串一起修改
                            // 先用 user_token 数据表中的token字段同样的加密算法对token进行加密，否则workerman无法识别用户身份
                            $sign                               = Common::getEncryptedToken($token) . 'fastchat_user_sign_additional';
                            $key                                = md5(md5($auth->id) . md5($sign));
                            $cookie_data                        = [$auth->id, $key];
                            $this->token_list['fastchat_token'] = implode('|', $cookie_data);
                        }
                    }
                }
            }

            if ($this->token_info && $this->token_list['fastchat_tourists_token']) {
                // 游客完成登录-游客信息转给用户
                Common::tourists_to_login($this->token_list['fastchat_tourists_token'], $this->token_info['user_id']);
            }

        }

        if (!$this->token_info && !$this->chat_config['anonymous_to_admin'] && !$this->chat_config['anonymous_to_user']) {
            $this->result(null, 403, $this->chat_config['chat_name'] . ' 禁止匿名用户', 'json');
        }

        if ($modulename != 'admin' && $this->token_list['fastchat_tourists_token'] && !$this->token_info) {
            // 验证游客身份
            $this->token_info = Common::check_tourists($this->token_list['fastchat_tourists_token']);
        }
    }

    public function initialize()
    {
        $config_data = $this->chat_config;
        $modulename  = $this->request->request('modulename');
        if (!$this->token_info) {
            if ($modulename != 'admin') {
                // 建立游客身份
                $tourists_max_id = Db::name('fastchat_tourists')->max('id');

                $token = Random::uuid();

                $tourists = [
                    'avatar'     => '',
                    'nickname'   => '游客 ' . $tourists_max_id,
                    'token'      => $token,
                    'createtime' => time()
                ];

                if (Db::name('fastchat_tourists')->insert($tourists)) {

                    $tourists_id              = Db::name('fastchat_tourists')->getLastInsID();
                    $keeptime                 = 864000;
                    $expiretime               = time() + $keeptime;
                    $key                      = md5(md5($tourists_id) . md5($keeptime) . md5($expiretime) . $token);
                    $fastchat_tourists_cookie = [$tourists_id, $keeptime, $expiretime, $key];

                    $fastchat_tourists                           = implode('|', $fastchat_tourists_cookie);
                    $this->token_list['fastchat_tourists_token'] = $fastchat_tourists;
                    Cookie::set('fastchat_user', $fastchat_tourists);

                    // 为游客登录
                    $this->token_info = Common::check_tourists($fastchat_tourists);

                } else {
                    $this->result(null, 401, $this->chat_config['chat_name'] . ' 游客创建失败！', 'json');
                }
            } else {
                $this->result(null, 401, $this->chat_config['chat_name'] . ' 未登陆', 'json');
            }
        }

        $info = Db::name('admin')->alias('a')->join('auth_group_access b','a.id = b.uid')->where('a.id',$this->token_info['id']
        )->where('b.group_id',10)->find();
        if($info){
            $config_data['search_tip'] = Common::search_tip_fill($config_data['session_type']);
            $config_data['new_msg']    = Common::get_unread_messages($this->token_info['user_id']);

            $config_data['user_info']   = $this->token_info;
            $config_data['token_list']  = $this->token_list;
            $config_data['window_html'] = $this->view->fetch(ROOT_PATH . 'public/assets/addons/fastchat/tpl/chat_window.html', [], ['__CDN__' => $this->chat_config['__CDN__']]);

            $this->result($config_data, 1, 'ok', 'json');
        }else{
            $this->result([], 1, 'ok', 'json');
        }
    }

    public function index()
    {
        $this->error("当前插件暂无前台页面");
    }

    public function upload()
    {
        $file = $this->request->file('file');
        if (empty($file)) {
            $this->result(null, 0, '没有文件被上传或上传超过限制', 'json');
        }

        //判断是否已经存在附件
        $sha1     = $file->hash();
        $extparam = $this->request->post();

        $upload = Config::get('upload');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type     = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size     = (int)$upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
        $fileInfo = $file->getInfo();
        $suffix   = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix   = $suffix ?: 'file';

        $mimetypeArr = explode(',', strtolower($upload['mimetype']));
        $typeArr     = explode('/', $fileInfo['type']);

        //禁止上传PHP和HTML文件
        if (in_array($fileInfo['type'], ['text/x-php', 'text/html']) || in_array($suffix, ['php', 'html', 'htm', 'phar', 'phtml']) || preg_match("/^php(.*)/i", $suffix)) {
            $this->error(__('上传格式限制'));
        }

        //Mimetype值不正确
        if (stripos($fileInfo['type'], '/') === false) {
            $this->error(__('上传格式限制'));
        }

        //验证文件后缀
        if ($upload['mimetype'] !== '*' &&
            (
                !in_array($suffix, $mimetypeArr)
                || (stripos($typeArr[0] . '/', $upload['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
            )
        ) {
            $this->error(__('上传格式限制'));
        }

        //验证是否为图片文件
        $imagewidth = $imageheight = 0;
        if (in_array($fileInfo['type'], ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']) || in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
            $imgInfo = getimagesize($fileInfo['tmp_name']);
            if (!$imgInfo || !isset($imgInfo[0]) || !isset($imgInfo[1])) {
                $this->error(__('上传的文件不是图片'));
            }
            $imagewidth  = $imgInfo[0] ?: $imagewidth;
            $imageheight = $imgInfo[1] ?: $imageheight;
        }

        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey    = $upload['savekey'];
        $savekey    = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName  = substr($savekey, strripos($savekey, '/') + 1);

        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
        if ($splInfo) {
            $admin_id = 0;
            $user_id  = 0;

            if ($this->token_info) {
                $user_info = Common::user_info($this->token_info['user_id']);

                if ($user_info['session_type'] == 0) {
                    $user_id = $user_info['id'];
                } elseif ($user_info['session_type'] == 1) {
                    $admin_id = $user_info['id'];
                }
            }

            $params     = array(
                'admin_id'    => $admin_id,
                'user_id'     => $user_id,
                'filesize'    => $fileInfo['size'],
                'imagewidth'  => $imagewidth,
                'imageheight' => $imageheight,
                'imagetype'   => $suffix,
                'imageframes' => 0,
                'mimetype'    => $fileInfo['type'],
                'url'         => $uploadDir . $splInfo->getSaveName(),
                'uploadtime'  => time(),
                'storage'     => 'local',
                'sha1'        => $sha1,
                'extparam'    => json_encode($extparam),
            );
            $attachment = model("common/attachment");
            $attachment->data(array_filter($params));
            $attachment->save();
            Hook::listen("upload_after", $attachment);
            $this->result(['url' => cdnurl($uploadDir . $splInfo->getSaveName(), true)], 1, null, 'json');
        } else {
            // 上传失败获取错误信息
            $this->result(null, 1, $file->getError(), 'json');
        }
    }

    /*供跨站下载来信提示音文件*/
    public function load_message_prompt()
    {
        $file = ROOT_PATH . 'public/assets/addons/fastchat/audio/message_prompt.wav';
        header("Content-type:application/octet-stream");
        $filename = basename($file);
        header("Content-Disposition:attachment;filename = " . $filename);
        header("Accept-ranges:bytes");
        header("Accept-length:" . filesize($file));
        readfile($file);
    }

}
